<template>
  <component
    ref="formRef"
    :is="getComponentByType('el-form')"
    :model="initialValues"
    @submit.prevent="handleSubmit"
    class="formwrapper"
    v-bind="elFormProps"
  >
    <template v-for="item in props.config" :key="item.prop">
      <component
        :is="getComponentByType('el-form-item')"
        :prop="item.prop"
        :label="item.label"
        :rules="item.rules"
        :label-width="item.labelWidth"
        :inline-message="item.inlineMessage ?? false"
        :style="{ width: getItemWidth(item) }"
      >
        <component
          v-if="item.type === 'el-upload'"
          :is="getComponentByType('el-upload')"
          v-model="initialValues[item.prop]"
          v-bind="item.componentProps"
          v-on="item.events || {}"
        />

        <template v-else-if="item.slotName">
          <slot
            :name="item.slotName"
            :initialValues="initialValues"
            :item="item"
          ></slot>
        </template>

        <component
          v-else-if="item.type && item.children"
          :is="getComponentByType(item.type)"
          v-model="initialValues[item.prop]"
          :placeholder="item.placeholder ?? '请输入' + item.label"
          v-bind="item.componentProps"
          v-on="item.events || {}"
        >
          <!-- 子组件 -->
          <template v-if="item.children && item.children.data.length">
            <component
              v-for="(child, CIndex) in item.children.data"
              :key="CIndex"
              :is="getComponentByType(item.children.type)"
              :placeholder="child.placeholder"
              :value="child.value"
              :label="child.label"
              v-bind="child.componentProps"
              v-on="item.events || {}"
            >
              <!-- 比如单选框el最新版如果使用lable会有警告,像按钮一样内部使用文字 -->
              <span v-if="child.htmlText">{{ child.htmlText }}</span>
            </component>
          </template>
        </component>

        <component
          v-else-if="item.type && !item.children"
          :is="getComponentByType(item.type)"
          v-model="initialValues[item.prop]"
          :placeholder="item.placeholder ?? '请输入' + item.label"
          v-bind="item.componentProps"
          v-on="item.events || {}"
        />
      </component>
    </template>
    <div v-if="props.footerShow">
      <component
        :is="getComponentByType('el-button')"
        type="primary"
        @click="handleSubmit"
        >提交</component
      >
      <component
        :is="getComponentByType('el-button')"
        @click="handleEvent('reset')"
        >重置</component
      >
    </div>
  </component>
</template>

<script setup lang="ts">
import { reactive, onMounted, ref, computed } from "vue";
import { ElForm } from "element-plus";
import { getComponentByType } from "./tools/elItem";
import {
  type FormItemConfig,
  type XFormApi,
  type XFormProps,
} from "./types/types";

const props = defineProps<XFormProps>();

// 提取el-form需要的属性，排除我们自定义的属性
const elFormProps = computed(() => {
  //  该页面 <el-form></el-form> 标签中使用过并且属于Form Attributes 中的参数 都需要排除掉，否则会失效 比如 model
  const { config, initialValues, footerShow, model, ...formProps } = props;
  return formProps;
});

const formData1 = reactive({ ...props.initialValues });

const formRef = ref<InstanceType<typeof ElForm>>();

/**
 * 提交表单
 * @returns {Promise<any>} 表单数据
 */
const handleSubmit = (): Promise<any> => {
  return new Promise((resolve, reject) => {
    formRef.value?.validate(async (valid) => {
      if (valid) {
        resolve(props.initialValues);
      } else {
        reject("表单验证失败");
      }
    });
  });
};
const handleEvent = (_eventName: string, ...args: any[]) => {
  //   emit(eventName, ...args);
  // console.log(eventName, ...args, "handleEvent");
  formRef.value?.resetFields();
};

const getItemWidth = (item: FormItemConfig) => {
  if (!item.width) {
    return "100%";
  }
  if (typeof item.width === "string") {
    return item.width;
  }
  if (typeof item.width === "number") {
    // 1~24  24=100%
    return `${(item.width * 100) / 24}%`;
  }
  return "100%";
};

const api: XFormApi = {
  register: function (): void {},
  /** 校验表单 */
  validate: () => formRef.value?.validate(),
  /** 重置表单 */
  resetFields: () => formRef.value?.resetFields(),
  /** 提交表单 */
  submit: handleSubmit,
};
const emit = defineEmits(["register"]);

onMounted(() => {
  emit("register", api);
});
</script>
<style scoped>
.formwrapper {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}

:deep(.el-form-item) {
  width: 100%;
}

:deep(.el-form-item__label) {
  position: relative;
}

:deep(.el-form-item__label::before) {
  position: absolute;
  left: -8px;
}
</style>
